import serial
import socket
import threading
import time
import logging
from request_queue import RequestQueue, SerialRequest
from client_handler import ClientHandler

logger = logging.getLogger('SerialBridge')

class SerialBridge:
    def __init__(self, config):
        self.config = config
        self.serial_port = None
        self.tcp_server = None
        self.clients = {}  # client_id -> ClientHandler
        self.running = False
        self.request_queue = RequestQueue(
            max_size=config['queue_size'],
            timeout=config['serial_timeout']
        )
        
        # 统计信息
        self.stats = {
            'bytes_sent': 0,
            'bytes_received': 0,
            'clients_connected': 0,
            'clients_disconnected': 0,
            'requests_processed': 0,
            'request_timeouts': 0,
            'start_time': time.time()
        }
        
        self.init_serial()

    def init_serial(self):
        """初始化串口"""
        try:
            self.serial_port = serial.Serial(
                port=self.config['serial_port'],
                baudrate=self.config['baudrate'],
                bytesize=self.config['bytesize'],
                parity=self.config['parity'],
                stopbits=self.config['stopbits'],
                timeout=0.1  # 短超时，用于非阻塞读取
            )
            logger.info(f"串口 {self.config['serial_port']} (TCP:{self.config['tcp_port']}) 已打开")
        except Exception as e:
            logger.error(f"打开串口 {self.config['serial_port']} 失败: {str(e)}")
            raise

    def start(self):
        """启动串口桥接服务"""
        self.running = True
        
        # 启动TCP服务器
        self.tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.tcp_server.bind(('0.0.0.0', self.config['tcp_port']))
        self.tcp_server.listen(5)
        logger.info(f"TCP服务器启动在端口 {self.config['tcp_port']} (串口: {self.config['serial_port']})")
        
        # 启动客户端接受线程
        accept_thread = threading.Thread(target=self._accept_clients)
        accept_thread.daemon = True
        accept_thread.start()
        
        # 启动串口处理线程
        serial_thread = threading.Thread(target=self._serial_processing_loop)
        serial_thread.daemon = True
        serial_thread.start()
        
        # 启动客户端清理线程
        cleanup_thread = threading.Thread(target=self._client_cleanup_loop)
        cleanup_thread.daemon = True
        cleanup_thread.start()
        
        # 启动统计线程
        stat_thread = threading.Thread(target=self._report_stats)
        stat_thread.daemon = True
        stat_thread.start()
        
        logger.info(f"串口服务器 {self.config['serial_port']} 已启动")

    def stop(self):
        """停止串口桥接服务"""
        self.running = False
        
        # 关闭所有客户端连接
        for client_id, client_handler in list(self.clients.items()):
            self._close_client(client_id)
        
        # 关闭TCP服务器
        if self.tcp_server:
            self.tcp_server.close()
        
        # 关闭串口
        if self.serial_port and self.serial_port.is_open:
            self.serial_port.close()
        
        logger.info(f"串口服务器 {self.config['serial_port']} (TCP:{self.config['tcp_port']}) 已停止")

    def _accept_clients(self):
        """接受客户端连接"""
        while self.running:
            try:
                client_socket, addr = self.tcp_server.accept()
                client_id = f"{addr[0]}:{addr[1]}"
                
                # 检查最大连接数
                if len(self.clients) >= self.config['max_clients']:
                    logger.warning(f"{self.config['serial_port']}: 达到最大连接数({self.config['max_clients']})，拒绝 {client_id}")
                    client_socket.close()
                    continue
                
                # 设置客户端超时
                client_socket.settimeout(1.0)  # 短超时，用于非阻塞检查
                
                # 创建客户端处理器
                client_handler = ClientHandler(
                    client_socket,
                    client_id,
                    self.request_queue,
                    self.config['client_timeout']
                )
                
                self.clients[client_id] = client_handler
                self.stats['clients_connected'] += 1
                
                # 启动客户端处理
                client_handler.start()
                
                logger.info(f"{self.config['serial_port']}: 客户端 {client_id} 已连接")
                
            except Exception as e:
                if self.running:
                    logger.error(f"接受客户端连接错误: {str(e)}")

    def _serial_processing_loop(self):
        """串口处理循环"""
        while self.running and self.serial_port and self.serial_port.is_open:
            try:
                # 获取下一个请求
                request = self.request_queue.get_next_request()
                
                if request:
                    # 检查客户端是否仍然连接
                    if request.client_id not in self.clients or not self.clients[request.client_id].is_connected():
                        logger.warning(f"客户端 {request.client_id} 已断开，跳过请求")
                        self.request_queue.complete_request(b'')  # 完成请求但不发送响应
                        continue
                    
                    # 发送请求数据到串口
                    self.serial_port.write(request.data)
                    self.stats['bytes_received'] += len(request.data)
                    
                    if self.config.get('debug', False):
                        logger.debug(f"{self.config['serial_port']}: {request.client_id} -> 串口: {request.data.hex()}")
                    
                    # 等待串口响应
                    response_data = self._wait_for_serial_response()
                    
                    if response_data:
                        # 完成请求并发送响应
                        self.request_queue.complete_request(response_data)
                        self.stats['bytes_sent'] += len(response_data)
                        self.stats['requests_processed'] += 1
                        
                        if self.config.get('debug', False):
                            logger.debug(f"{self.config['serial_port']}: 串口 -> {request.client_id}: {response_data.hex()}")
                    else:
                        # 超时处理
                        self.stats['request_timeouts'] += 1
                        logger.warning(f"{self.config['serial_port']}: 请求超时，客户端 {request.client_id}")
                        self.request_queue.complete_request(b'')  # 发送空响应
                else:
                    # 没有请求时休眠片刻
                    time.sleep(0.1)
                    
            except Exception as e:
                logger.error(f"{self.config['serial_port']}: 串口处理错误: {str(e)}")
                time.sleep(1)

    def _wait_for_serial_response(self):
        """等待串口响应"""
        response = b''
        start_time = time.time()
        timeout = self.config['serial_timeout']
        
        while time.time() - start_time < timeout:
            try:
                # 读取串口数据
                data = self.serial_port.read(self.serial_port.in_waiting or 1)
                if data:
                    response += data
                    start_time = time.time()  # 重置超时计时器
                else:
                    # 如果没有数据，短暂休眠
                    time.sleep(0.01)
            except Exception as e:
                logger.error(f"{self.config['serial_port']}: 读取串口错误: {str(e)}")
                break
        
        return response if response else None

    def _client_cleanup_loop(self):
        """客户端清理循环，定期检查并清理已断开的客户端"""
        while self.running:
            try:
                time.sleep(2)  # 每2秒检查一次
                
                # 检查所有客户端连接状态
                disconnected_clients = []
                for client_id, client_handler in list(self.clients.items()):
                    if not client_handler.is_connected():
                        disconnected_clients.append(client_id)
                
                # 清理已断开的客户端
                for client_id in disconnected_clients:
                    self._close_client(client_id)
                    
            except Exception as e:
                logger.error(f"{self.config['serial_port']}: 客户端清理错误: {str(e)}")

    def _close_client(self, client_id):
        """关闭客户端连接"""
        if client_id in self.clients:
            client_handler = self.clients.pop(client_id)
            client_handler.close()
            
            # 移除该客户端的请求
            self.request_queue.remove_client_requests(client_id)
            
            self.stats['clients_disconnected'] += 1
            logger.info(f"{self.config['serial_port']}: 客户端 {client_id} 已断开")

    def _report_stats(self):
        """定期报告统计信息"""
        while self.running:
            time.sleep(60)  # 每分钟报告一次
            uptime = time.time() - self.stats['start_time']
            logger.info(
                f"{self.config['serial_port']} 统计: "
                f"运行 {int(uptime//3600)}h {int((uptime%3600)//60)}m, "
                f"发送 {self.stats['bytes_sent']} 字节, "
                f"接收 {self.stats['bytes_received']} 字节, "
                f"处理 {self.stats['requests_processed']} 请求, "
                f"超时 {self.stats['request_timeouts']} 请求, "
                f"活跃客户端 {len(self.clients)}"
            )